<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8" />
<title>Editor.md Application</title>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="editor.md/examples/css/style.css" />
<link rel="stylesheet" href="editor.md/css/editormd.css" />   
<link rel="stylesheet" href="Zebra_Dialog/public/css/default/zebra_dialog.css" type="text/css" />
<script src="editor.md/examples/js/jquery.min.js"></script>
<script src="Zebra_Dialog/public/javascript/zebra_dialog.src.js"></script>
<script src="editor.md/editormd.js"></script>
<script src="to-markdown/src/to-markdown.js"></script>
<script src="to-markdown/src/he.js"></script>
<script type="text/javascript">

/*****************************************************************************
 * fs               -- 文件系统操作对象
 * win              -- 窗口操作对象
 * markdownEditor   -- Markdown编辑器对象
 * markdownChanged  -- 表示Markdown是否修改
 * markdownFilename -- 表示当前已经打开的Markdown文件名
 * markdownURL      -- HTML转Markdown的URL路径
 * markdownFilter   -- HTML转Markdown的过滤器
 * openChooser      -- 打开Markdown文件对象
 * saveChooser      -- 保存Markdown文件对象
 * dragChooser      -- 拖曳Markdown文件对象
 ****************************************************************************/
var fs = require("fs");
var win = require("nw.gui").Window.get();
var markdownEditor;
var markdownChanged = false;
var markdownFilename = "";
var markdownURL = "";
var openChooser;
var saveChooser;
var dragChooser;
var markdownFilter = [
	{
		"domain": "blog.csdn.net",
		"main_id": "main",
		"main_class": "",
		"id":["report_dialog", "digg", "pop_win", "d-top", "ad_cen", "ad_bot",
			"popup_mask", "job_blog_reco"],
		"class":["tag_list", "article_manage", "tag2box", "comment_class", 
			"bdsharebuttonbox", "article_next_prev", "blog-associat-tag",
			"blog-ass-articl", "ad_class", "clear"],
		"tag":["link", "script", "style"]
	},
	{
		"domain":"www.csdn.net",
		"main_id": "",
		"main_class":"content",
		"id":[],
		"class":["tit_bar", "tag", "share", "digg", "related", "ad_475_60",
			"relational", "csdn_comments", "right"],
		"tag":["script"]
	},
	{
		"domain": "my.oschina.net",
		"main_id": "",
		"main_class": "BlogEntity",
		"id":[],
		"class":["BlogStat", "BlogLinks", "BlogCopyright", "BlogShare"],
		"tag":[]
	},
	{
		"domain":"www.oschina.net",
		"main_id":"",
		"main_class":"NewsBody",
		"id":[],
		"class":["PubDate", "NewsToolbar", "Comments", "CommentForm", 
			"RelatedNews", "RelatedThreads", "NewsLinks", "NewsPrevAndNext",
			"SimpleNewsList", "copyright", "lbox", "HomeHotNews"],
		"tag":["link", "script", "style", "table"]
	},
	{
		"domain":"www.oschina.net/translate",
		"main_id":"",
		"main_class":"Article",
		"id":[],
		"class":["translater", "Tags", "rec_user", "Vote", "toolbar", 
			"comments"],
		"tag":[]
	},
	{
		"domain":"www.cnblogs.com",
		"main_id":"",
		"main_class":"post",
		"id":[],
		"class":["postfoot"],
		"tag":[]
	},
	{
		"domain":"blog.163.com",
		"main_id":"",
		"main_class":"mcnt",
		"id":[],
		"class":["snl", "nbw-act", "comment", "relateblog", "author"],
		"tag":[]
	}
];

/*****************************************************************************
 *
 * 函数: message
 *
 * 功能: 消息函数
 *
 * 参数: msg -- 消息字符串
 *
 * 返回: 无
 *
 ****************************************************************************/
function message(msg) {
	$.Zebra_Dialog('<strong>' + msg + '</strong>', {
		"title": '错误',
		"type": 'error',
		"show_close_button": false
	});
}

/*****************************************************************************
 *
 * 函数: changedTitle
 *
 * 功能: 修改标题
 *
 * 参数: changed -- 表示当前编辑的文件内容是否改变
 *
 * 返回: 无
 *
 ****************************************************************************/
function changeTitle(changed) {
	var title = "";

	if(changed) {
		title = "Editor.md Application(*" + markdownFilename + ")";
	} else {
		title = "Editor.md Application(" + markdownFilename + ")";
	}
	
	document.title = "";
	document.title = title;
}

/*****************************************************************************
 *
 * 函数: writeFile
 *
 * 功能: 从Markdown编辑器中获取Markdown代码直接保存的文件中
 *
 * 参数: filename -- markdown文件名
 *       callback -- 保存成功的回调函数
 *
 * 返回: 无
 *
 ****************************************************************************/
function writeFile(filename, callback) {
	var markdown = markdownEditor.getMarkdown();
	fs.writeFile(filename, markdown, function (error) {
		if (error) {
			message("文件保存失败!")
		} else {
			markdownChanged = false;
			markdownFilename = filename;
			changeTitle(false);
			if(callback != null) {
				callback();
			}
		}
	});
}

/*****************************************************************************
 *
 * 函数: readFile
 *
 * 功能: 从文件中直接读取Markdown代码,并设置到Markdown编辑器中
 *
 * 参数: filename -- markdown文件名
 *       callback -- 读取成功的回调函数
 *
 * 返回: 无
 *
 ****************************************************************************/
function readFile(filename, callback) {
	fs.readFile(filename, 'utf-8', function (error, contents) {
		if (error) {
			message("文件打开失败!")
		} else {
			markdownEditor.setMarkdown(contents);
			markdownChanged = false;
			markdownFilename = filename;
			changeTitle(false);
			$("base").attr("href", getURIPath(filename));
			if(callback != null) {
				callback();
			}
		}
	});
}

/*****************************************************************************
 *
 * 函数: windown onclose event
 *
 * 功能: 注册Window关闭事件的监听处理功能
 *
 * 参数: 无
 *
 * 返回: 无
 *
 ****************************************************************************/
win.on('close', function() {
	if(markdownChanged) {
		$.Zebra_Dialog('<strong>文档发生变化,是否需要保存?</strong>', {
			'type':     'question',
			'title':    '询问',
			'buttons':  ['保存退出', '不保存退出', '取消退出'],
			'show_close_button': false,
			'onClose':  function(caption) {
				if(caption == "保存退出") {
					saveMarkdown(function(){ win.close(true); });
				} else if(caption == "不保存退出") {
					win.close(true);
				} else {
					/*取消退出,什么也不做*/
				}
			}
		});
	}
	else {
		this.close(true);
	}
});

console.log("exepath:", process.execPath);
console.log("mode path:", process.cwd());

/*****************************************************************************
 *
 * 函数: getURIPath
 *
 * 功能: 从本地绝对路径的文件名中提取URI资源路径 
 *
 * 参数: filename 文件名(如D:\example\abc.md)
 *
 * 返回: URI资源路径
 *
 ****************************************************************************/
function getURIPath(filename) {
	var uri = "";
	var pos = 0;

	pos = filename.lastIndexOf("\\");
	uri = "file:\\\\\\" + filename.substring(0, parseInt(pos) + 1);
	uri = uri.replace(new RegExp("%20","gm")," ");
	return uri.toString();
}

/*****************************************************************************
 *
 * 函数: getHost
 *
 * 功能: 获取URL的主机名
 *
 * 参数: url -- URL路径
 *
 * 返回: 主机名
 *
 ****************************************************************************/
function getHost(url) {
	var host = "null";
	if((typeof url == "undefined") || (null == url)) {
		url = window.location.href;
	}
	
	var regex = /.*\:\/\/([^\/]*).*/;
	var match = url.match(regex);
	if((typeof match != "undefined") && (null != match)) {
		host = match[1];
	}
	return host;
}

/*****************************************************************************
 *
 * 函数: openDebug
 *
 * 功能: 打开Node-Webkit内置的调试窗口
 *
 * 参数: 无
 *
 * 返回: 无
 *
 ****************************************************************************/
function openDebug() {
	win.showDevTools();
}

/*****************************************************************************
 *
 * 函数: openMarkdown
 *
 * 功能: 打开本地Markdown文件
 *
 * 参数: 无
 *
 * 返回: 无
 *
 ****************************************************************************/
function openMarkdown() {
	var open = function() {
		openChooser.value = "";
		openChooser.callback = null;
		openChooser.click();
	}

	if(markdownChanged) {
		$.Zebra_Dialog('当前文档已修改未保存,是否需要保存?', {
			'type':     'question',
			'title':    '打开新文档询问',
			'buttons':  ['保存', '丢弃', '取消打开'],
			'show_close_button': false,
			'onClose':  function(caption) {
				if(caption == "保存") {
					saveMarkdown(open);
				} else if(caption == "丢弃") {
					open();
				} else if(caption == '取消打开'){
					/*取消退出,什么也不做*/
				}
			}
		});
	} else {
		open();
	}
}

/*****************************************************************************
 *
 * 函数: saveMarkdown
 *
 * 功能: 保存Markdown到本地文件
 *
 * 参数: callback -- 保存文件完成后的回调函数
 *
 * 返回: 无
 *
 ****************************************************************************/
function saveMarkdown(callback) {
	if(typeof(callback) != "function") {
		callback = null;
	}

	if(markdownFilename == "") {
		saveChooser.value = "";
		saveChooser.callback = callback;
		saveChooser.click();
	} else {
		writeFile(markdownFilename, callback);
	}
}

/*****************************************************************************
 *
 * 函数: dragMarkdown
 *
 * 功能: 支持Markdown文件的拖曳操作 
 *
 * 参数: e -- 拖曳事件对象
 *
 * 返回: 无
 *
 ****************************************************************************/
function dragMarkdown(e) {
	var fileList = e.dataTransfer.files;
	var extend = "";
	var name = "";
	var index = 0;

	if((fileList.length == 0) || (fileList.length > 1)) {
		message("目前只支持拖曳一个文件.");
		return;
	}

	name = fileList[0].name.toLowerCase();
	for(index = name.length; (index > 0) && (name[index] != '.'); index--) {
		extend += name.charAt(index);
	}

	if((extend != "dm") && (extend != 'nwodkram')){
		message("目前只支持Markdown文件.");
		return;
	}

	var load = function() {
		readFile(fileList[0].path, null);
	}

	if(markdownChanged) {
		$.Zebra_Dialog('当前文档已修改未保存,是否需要保存?', {
			'type':     'question',
			'title':    '拖曳新文档询问',
			'buttons':  ['保存', '丢弃', '取消拖曳'],
			'show_close_button': false,
			'onClose':  function(caption) {
				if(caption == "保存") {
					saveMarkdown(load);
				} else if(caption == "丢弃") {
					load();
				} else if(caption == '取消拖曳') {
					/*取消拖曳,什么也不做*/
				}
			}
		});
	} else {
		load();
	}
}

/*****************************************************************************
 *
 * 函数: htmlFilter
 *
 * 功能: 对HTML无用的内容进行过滤,只把有用的内容保留下来
 *
 * 参数: data -- 通过AJAX请求获取到的HTML源代码
 *       url  -- 当前AJAX请求的URL路径
 *
 * 返回: 过滤后的HTML源代码
 *
 ****************************************************************************/
function htmlFilter(data, url) {
	var dom = $(data);
	var main;
	var filter = null;
	var node;
	var index = 0;
	var result = "";
	var host = getHost(url);

	for(index = 0; index < markdownFilter.length; index++) {
		if(host == markdownFilter[index].domain) {
			filter = markdownFilter[index];
			break;
		}
	}

	if(filter == null) {
		main = dom;
	} else if(filter.main_id != "") {
		main = $("#" + filter.main_id, dom);
	} else if(filter.main_class != "") {
		main = $("." + filter.main_class, dom);
	} else {
		main = dom;
	}

	/*移除所有不必要的标签,link,script,style等*/
	for(index = 0; index < filter.tag.length; index++) {
		console.log("remove tag:", filter.tag[index]);
		node = $(filter.tag[index], main);
		$(node).remove();
	}

	for(index = 0; index < filter.id.length; index++) {
		console.log("remove id:", filter.id[index]);
		node = $("#" + filter.id[index], main);
		$(node).remove();
	}

	for(index = 0; index < filter.class.length; index++) {
		console.log("remove class:", filter.class[index]);
		node = $("." + filter.class[index], main);
		$(node).remove();
	}

	/*************************************************************************
	 *单纯的对div进行each的时候,发现不能完全的把每个div都替换了,因为父节点替换
	 *后子节点的结构已经发生了变化,所以只好返回,重新查找div节点,直到没有div节
	 *点才停止替换.
     ************************************************************************/
	do{
		var div = $("div", main);
		div.each(function() {  
			var text = $(this).html();
			$(this).replaceWith(text);  
		});
	}while(div.length > 0);

	do{
		var span = $("span", main);
		span.each(function() {
			var text = $(this).html();
			$(this).replaceWith(text);
		});
	}while(span.length > 0);

	/*删除注释*/
	result = main.html();
	result = result.replace(/<!--.*-->/gim,"");

	return result; 
}

/*****************************************************************************
 *
 * 函数: htmlConvert
 *
 * 功能: HTML代码转换为Markdown
 *
 * 参数: 无
 *
 * 返回: 无
 *
 ****************************************************************************/
function htmlConvert() {
	var get = function(urlstr) {
		$.ajax({
			type: "get",
			url: urlstr,
			beforeSend: function(XMLHttpRequest){
				//ShowLoading();
				console.log("ajax start");
			},
			success: function(data, textStatus){
				var html = htmlFilter(data, urlstr);
				var markdown = toMarkdown(html);
				markdownEditor.setMarkdown(markdown);
			},
			complete: function(XMLHttpRequest, textStatus){
				//HideLoading();
				console.log("ajax end");
			},
			error: function(){
				//Error
			}
		});
	}

	var msg = '<strong>URL:</strong><input id="url"';
	msg += ' onchange="markdownURL=this.value;" type="text"/>';

	$.Zebra_Dialog(msg, {
		'type':     'question',
		'title':    'HTML转Markdown',
		'buttons':  ['转换', '取消'],
		'show_close_button': false,
		'onClose':  function(caption) {
			if(caption == "转换") {
				get(markdownURL);
			}
		}
	});
}

/*****************************************************************************
 *
 * 函数: editorMarkdownAppToolbar
 *
 * 功能: 加载预置的编辑器工具栏图标
 *
 * 参数: 无
 *
 * 返回: 无
 *
 ****************************************************************************/
function editorMarkdownAppToolbar() {
	var open = "";
	var save = "";
	var divider = "";
	var debug = "";
	var html = "";

	divider = '<li class="divider" unselectable="on">|</li>';

	debug += '<li><a id="debug-btn" title="调试" unselectable="on">';
	debug += '<i class="fa fa-bars" name="debug" unselectable="on"></i>';
	debug += '</a></li>';

	html += '<li><a id="html-btn" title="转换HTML到Markdown" unselectable="on">';
	html += '<l class="fa fa-html5" name="html" unselectable="on"></i>';
	html += '</a></li>';

	save += '<li><a id="save-btn" title="保存Markdown" unselectable="on">';
	save += '<i class="fa fa-save" name="save" unselectable="on"></i>';
	save += '</a></li>';

	open += '<li><a id="open-btn" title="打开Markdown" unselectable="on">';
	open += '<i class="fa fa-file-o" name="open" unselectable="on"></i>';
	open += '</a></li>';

	$(".editormd-menu").prepend(divider);
	$(".editormd-menu").prepend(debug);
	$(".editormd-menu").prepend(html);
	$(".editormd-menu").prepend(save);
	$(".editormd-menu").prepend(open);
	$("#debug-btn").bind('click', openDebug);
	$("#html-btn").bind('click', htmlConvert);
	$("#open-btn").bind('click', openMarkdown);
	$("#save-btn").bind('click', saveMarkdown);
}

/*****************************************************************************
 *
 * 函数: $(function())
 *
 * 功能: 创建Markdown编辑器对象
 *
 * 参数: 无
 *
 * 返回: 无
 *
 ****************************************************************************/
$(function() {
	openChooser = document.querySelector("#open");
	saveChooser = document.querySelector("#save");
	dragChooser = document.body;

	openChooser.addEventListener("change", function(evt) {
		readFile(this.value, this.callback);
	});
	saveChooser.addEventListener("change", function(evt) {
		writeFile(this.value, this.callback);
	});

	dragChooser.addEventListener('dragenter', function(e) {
		e.preventDefault();
	}, false);

	dragChooser.addEventListener('dragleave', function(e) {
		e.preventDefault();
	}, false);

	dragChooser.addEventListener('dragover', function(e) {
		e.stopPropagation();
		e.preventDefault();
	}, false);

	dragChooser.addEventListener('drop', function(e) {
		e.preventDefault();
		dragMarkdown(e);
	}, false);

	win.maximize();
	markdownEditor = editormd("editormd", {
		width: "100%",
		height: $(document).height(),
		path : 'editor.md/lib/',
		markdown : "",
		codeFold : true,
		saveHTMLToTextarea : true,
		searchReplace : true,
		htmlDecode : true,
		emoji : true,
		taskList : true,
		tex : true,
		flowChart : true,
		sequenceDiagram : true,
		imageUpload : true,
		imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
		imageUploadURL : "./php/upload.php",
		onload : function() {
			console.log('onload', this);
			this.fullscreen();
			editorMarkdownAppToolbar();
		},
		onchange : function() {
			markdownChanged = true;
			changeTitle(true);
		}
	});
});
</script>
<base href="">
<style>
#open {
	display:none;
}

#save {
	display:none;
}
</style>
</head>
<body>
	<input type="file" id="open" accept=".md,.markdown" />
	<input type="file" id="save" nwsaveas="filename.md" />
	<div id="layout"><div id="editormd"></div></div>
</body>
</html>

